﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MontagsmalerApp
{
	/// <summary>
	/// Interaktionslogik für Spielerverwaltung.xaml
	/// </summary>
	public partial class SpielerverwaltungPflege : UserControl
	{
		#region Properties
		private Spielerverwaltung spielerverwaltung;
		private const string einzelspielerFormat = "einzelspieler";
		#endregion

		#region Constructor
		public SpielerverwaltungPflege()
		{
			InitializeComponent();
			spielerverwaltung = Spielerverwaltung.Instance;

			Refresh();
		}
		#endregion

		#region Events
		private void btnNeuerSpieler_Click(object sender, RoutedEventArgs e)
		{
			if (!string.IsNullOrEmpty(txtSpielerName.Text))
			{
				string name = txtSpielerName.Text;
				NeuerSpieler(name);
			}
		}

		private void btnNeuesTeam_Click(object sender, RoutedEventArgs e)
		{
			if (!string.IsNullOrEmpty(txtTeamName.Text))
			{
				string name = txtTeamName.Text;
				NeuesTeam(name);
			}
		}

		private void btnLoescheTeam_Click(object sender, RoutedEventArgs e)
		{
			if (treeTeams.SelectedItem != null)
			{
				if (treeTeams.SelectedItem is Spielerteam)
				{
					// Team löschen
					spielerverwaltung.TeamLoeschen((Spielerteam)treeTeams.SelectedItem);
				}
				else if (treeTeams.SelectedItem is Einzelspieler)
				{
					// Spieler aus dem Team entfernen
					spielerverwaltung.SpielerAusTeamEntfernen((Einzelspieler)treeTeams.SelectedItem);
				}
			}

			Refresh();
		}

		private void btnLoescheSpieler_Click(object sender, RoutedEventArgs e)
		{
			if (treeSpieler.SelectedItem != null)
			{
				if (treeSpieler.SelectedItem is Einzelspieler)
				{
					// Spieler aus dem Team entfernen
					spielerverwaltung.SpielerEntfernen((Einzelspieler)treeSpieler.SelectedItem);
				}
			}

			Refresh();
		}
		#endregion

		#region Methoden
		private void NeuerSpieler(string name)
		{
			try
			{
				spielerverwaltung.NeuerSpieler(name);
				txtSpielerName.Text = "";
				Refresh();
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
		}

		private void NeuesTeam(string name)
		{
			try
			{
				spielerverwaltung.NeuesTeam(name);
				txtTeamName.Text = "";
				Refresh();
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
		}

		public void Refresh()
		{
			//TODO Geht das nicht einfacher bzw. muss das wirklich sein?
			treeTeams.ItemsSource = null;
			treeTeams.ItemsSource = spielerverwaltung.Spielerteams;

			treeSpieler.ItemsSource = null;
			treeSpieler.ItemsSource = spielerverwaltung.AlleSpieler;
		}

		public void PunkteZuruecksetzen()
		{
			spielerverwaltung.AllePunkteZuruecksetzen();
			Refresh();
		}
		#endregion

		#region DragDrop
		/// <summary>
		/// Gibt an, ob gerade ein Objekt festgehalten wird.
		/// </summary>
		private bool IsDragging;

		/// <summary>
		/// Der Startpunkt des Drag and Drops.
		/// </summary>
		private Point _startPointDragDrop;

		/// <summary>
		/// Wird ein Spieler-Objekt über dem Tree für die Teams fallengelassen, dann wird dieser dem Team hinzugefügt.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void treeTeams_Drop(object sender, DragEventArgs e)
		{
			e.Effects = DragDropEffects.None;
			e.Handled = true;

			IDataObject data = e.Data;
			if (data.GetDataPresent(einzelspielerFormat))
			{
				Einzelspieler draggedSpieler = (Einzelspieler)data.GetData(einzelspielerFormat);

				// Verify that this is a valid drop and then store the drop target
				TreeViewItem TargetItem = GetNearestContainer(e.OriginalSource as UIElement);
				if (TargetItem != null)
				{
					if (TargetItem.Header is Spielerteam)
					{
						Spielerteam team = (Spielerteam)TargetItem.Header;
						spielerverwaltung.SpielerZuweisen(draggedSpieler, team);
						e.Effects = DragDropEffects.Move;
					}
					else if (TargetItem.Header is Einzelspieler)
					{
						Einzelspieler spieler = (Einzelspieler)TargetItem.Header;
						Spielerteam team = spielerverwaltung.GetTeamBySpieler(spieler);
						if (team != null)
						{
							spielerverwaltung.SpielerZuweisen(draggedSpieler, team);
							e.Effects = DragDropEffects.Move;
						}
					}
				}
			}

			Refresh();
		}

		/// <summary>
		/// Merkt ein bevorstehendes Drag and Drop.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void UserControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
			_startPointDragDrop = e.GetPosition(null);
		}

		/// <summary>
		/// Prüft, ob ein Einzelspielerobjekt ausgewählt wurde und führt dann einen Drag and Drop durch.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void UserControl_PreviewMouseMove(object sender, MouseEventArgs e)
		{
			if (e.LeftButton == MouseButtonState.Pressed && !IsDragging)
			{
				// Prüfe, ob auch wirklich ein DragDrop gewünscht ist, indem der zurückgelegte Weg mit der Maus (mit gedrückter Taste) dem Minimum entspricht
				Point position = e.GetPosition(null);
				if (Math.Abs(position.X - _startPointDragDrop.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(position.Y - _startPointDragDrop.Y) > SystemParameters.MinimumVerticalDragDistance)
				{
					//Prüfe, aus welchem TreeView welcher Einzelspieler gerade gezogen wird
					// TreeSpieler
					DependencyObject dependencyObject = treeSpieler.InputHitTest(e.GetPosition(treeSpieler)) as DependencyObject;
					if (dependencyObject != null && treeSpieler.SelectedItem is Einzelspieler)
					{
						Einzelspieler draggedSpieler = treeSpieler.SelectedItem as Einzelspieler;
						StartDrag(draggedSpieler);
					}
					else
					{
						//TreeTeams
						dependencyObject = treeTeams.InputHitTest(e.GetPosition(treeTeams)) as DependencyObject;
						if (dependencyObject != null && treeTeams.SelectedItem is Einzelspieler)
						{
							Einzelspieler draggedSpieler = (Einzelspieler)treeTeams.SelectedItem;
							StartDrag(draggedSpieler);
						}
					}
				}
			}
		}

		/// <summary>
		/// Führt ein Drag and Drop mit einem Einzelspieler-Objekt durch.
		/// </summary>
		/// <param name="draggedSpieler"></param>
		private void StartDrag(Einzelspieler draggedSpieler)
		{
			IsDragging = true;

			if (draggedSpieler != null)
			{
				DataObject data = new DataObject(einzelspielerFormat, draggedSpieler);
				DragDropEffects de = DragDrop.DoDragDrop(this.treeSpieler, data, DragDropEffects.Move);
			}

			IsDragging = false;
		}

		/// <summary>
		/// Sucht den nächsten TreeViewItem an der Position.
		/// </summary>
		/// <param name="element"></param>
		/// <returns></returns>
		private TreeViewItem GetNearestContainer(UIElement element)
		{
			// Walk up the element tree to the nearest tree view item.
			TreeViewItem container = element as TreeViewItem;
			while ((container == null) && (element != null))
			{
				element = VisualTreeHelper.GetParent(element) as UIElement;
				container = element as TreeViewItem;
			}
			return container;
		}
		#endregion

	}
}
